package com.kedacom.demo.redis.springdataredis;

import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.StringRedisTemplate;

import com.kedacom.demo.utils.StringSerializer;

/**
 * BaseRedisDao
 * @author luocanfeng
 * @date 2015年9月1日
 */
public abstract class BaseRedisDao {

	protected Logger logger = LoggerFactory.getLogger(getClass());

	@Resource
	protected StringRedisTemplate redisTemplate;

	/**
	 * 设置指定key的值
	 */
	private void set(final byte[] key, final byte[] value, final long expireInSeconds) {
		redisTemplate.execute(new RedisCallback<Boolean>() {

			public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
				if (expireInSeconds > 0) {
					connection.setEx(key, expireInSeconds, value);
				} else {
					connection.set(key, value);
				}
				return true;
			}
		});
	}

	/**
	 * 设置指定key的值
	 */
	public void set(String key, String value, long expireInSeconds) {
		this.set(StringSerializer.toByteArray(key), StringSerializer.toByteArray(value), expireInSeconds);
	}

	/**
	 * 设置指定key的值
	 */
	public void set(String key, String value) {
		this.set(key, value, 0L);
	}

	/**
	 * 获取指定key的值
	 */
	private byte[] get(final byte[] key) {
		return redisTemplate.execute(new RedisCallback<byte[]>() {

			public byte[] doInRedis(RedisConnection connection) throws DataAccessException {
				byte[] result = connection.get(key);
				logger.debug("{}", result);
				return result;
			}
		});
	}

	/**
	 * 获取指定key的值
	 */
	public String get(String key) {
		return StringSerializer.fromByteArray(this.get(StringSerializer.toByteArray(key)));
	}

	/**
	 * 获取指定key列表对应的值列表
	 */
	private List<byte[]> mGet(final byte[]... keys) {
		return redisTemplate.execute(new RedisCallback<List<byte[]>>() {

			public List<byte[]> doInRedis(RedisConnection connection) throws DataAccessException {
				return connection.mGet(keys);
			}
		});
	}

	/**
	 * 获取指定key列表对应的值列表
	 */
	public List<String> mGet(String... keys) {
		return StringSerializer.fromBytesList(this.mGet(StringSerializer.toBytesArray(keys)));
	}

	/**
	 * 删除指定key列表
	 */
	private long del(final byte[]... keys) {
		return redisTemplate.execute(new RedisCallback<Long>() {

			public Long doInRedis(RedisConnection connection) throws DataAccessException {
				return connection.del(keys);
			}
		});
	}

	/**
	 * 删除指定key列表
	 */
	public long del(final String... keys) {
		// return redisTemplate.delete(Arrays.asList(keys));
		return this.del(StringSerializer.toBytesArray(keys));
	}

	/**
	 * 获取符合指定pattern的key列表
	 */
	public Set<String> keys(String pattern) {
		return redisTemplate.keys(pattern);
	}

	/**
	 * 判断是否存在指定key
	 */
	private boolean exists(final byte[] key) {
		return redisTemplate.execute(new RedisCallback<Boolean>() {

			public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
				return connection.exists(key);
			}
		});
	}

	/**
	 * 判断是否存在指定key
	 */
	public boolean exists(String key) {
		return this.exists(StringSerializer.toByteArray(key));
	}

	/**
	 * 设置hash值
	 */
	private void hMSet(final byte[] key, final Map<byte[], byte[]> hashes) {
		redisTemplate.execute(new RedisCallback<Boolean>() {

			public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
				connection.hMSet(key, hashes);
				return true;
			}
		});
	}

	/**
	 * 设置hash值
	 */
	public void hMSet(String key, final Map<String, String> hashes) {
		this.hMSet(StringSerializer.toByteArray(key), StringSerializer.toByteMap(hashes));
	}

	/**
	 * 设置指定key的hash中的指定field值
	 */
	private long hSet(final byte[] key, final byte[] field, final byte[] value) {
		return redisTemplate.execute(new RedisCallback<Long>() {

			public Long doInRedis(RedisConnection connection) throws DataAccessException {
				// FIXME: see http://redis.io/commands/hset#return-value
				return connection.hSet(key, field, value) ? 1L : 0L;
			}
		});
	}

	/**
	 * 设置指定key的hash中的指定field值
	 */
	public long hSet(String key, String field, String value) {
		return this.hSet(StringSerializer.toByteArray(key), StringSerializer.toByteArray(field),
				StringSerializer.toByteArray(value));
	}

	/**
	 * 获取指定key的hash值
	 */
	private Map<byte[], byte[]> hGetAll(final byte[] key) {
		return redisTemplate.execute(new RedisCallback<Map<byte[], byte[]>>() {

			public Map<byte[], byte[]> doInRedis(RedisConnection connection) throws DataAccessException {
				return connection.hGetAll(key);
			}
		});
	}

	/**
	 * 获取指定key的hash值
	 */
	public Map<String, String> hGetAll(String key) {
		return StringSerializer.fromByteMap(this.hGetAll(StringSerializer.toByteArray(key)));
	}

	/**
	 * 获取指定key的hash中的指定field值
	 */
	private byte[] hGet(final byte[] key, final byte[] field) {
		return redisTemplate.execute(new RedisCallback<byte[]>() {

			public byte[] doInRedis(RedisConnection connection) throws DataAccessException {
				return connection.hGet(key, field);
			}
		});
	}

	/**
	 * 获取指定key的hash中的指定field值
	 */
	public String hGet(String key, String field) {
		return StringSerializer.fromByteArray(this.hGet(StringSerializer.toByteArray(key),
				StringSerializer.toByteArray(field)));
	}

	/**
	 * 删除指定key的hash中的指定field列表
	 */
	private long hDel(final byte[] key, final byte[]... fields) {
		return redisTemplate.execute(new RedisCallback<Long>() {

			public Long doInRedis(RedisConnection connection) throws DataAccessException {
				return connection.hDel(key, fields);
			}
		});
	}

	/**
	 * 删除指定key的hash中的指定field列表
	 */
	public long hDel(String key, String... fields) {
		return this.hDel(StringSerializer.toByteArray(key), StringSerializer.toBytesArray(fields));
	}

	/**
	 * 判断指定key的hash是否存在指定field
	 */
	private boolean hExists(final byte[] key, final byte[] field) {
		return redisTemplate.execute(new RedisCallback<Boolean>() {

			public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
				return connection.hExists(key, field);
			}
		});
	}

	/**
	 * 判断指定key的hash是否存在指定field
	 */
	public boolean hExists(String key, String field) {
		return this.hExists(StringSerializer.toByteArray(key), StringSerializer.toByteArray(field));
	}

	/**
	 * 在指定key的set上添加指定的value列表
	 */
	private long sAdd(final byte[] key, final byte[]... values) {
		return redisTemplate.execute(new RedisCallback<Long>() {

			public Long doInRedis(RedisConnection connection) throws DataAccessException {
				return connection.sAdd(key, values);
			}
		});
	}

	/**
	 * 在指定key的set上添加指定的value列表
	 */
	public long sAdd(String key, String... values) {
		return this.sAdd(StringSerializer.toByteArray(key), StringSerializer.toBytesArray(values));
	}

	/**
	 * 获取指定key的set
	 */
	private Set<byte[]> sMembers(final byte[] key) {
		return redisTemplate.execute(new RedisCallback<Set<byte[]>>() {

			public Set<byte[]> doInRedis(RedisConnection connection) throws DataAccessException {
				return connection.sMembers(key);
			}
		});
	}

	/**
	 * 获取指定key的set
	 */
	public Set<String> sMembers(String key) {
		return StringSerializer.fromBytesSet(this.sMembers(StringSerializer.toByteArray(key)));
	}

	/**
	 * 获取指定key列表所有set的并集
	 */
	private Set<byte[]> sUnion(final byte[]... keys) {
		return redisTemplate.execute(new RedisCallback<Set<byte[]>>() {

			public Set<byte[]> doInRedis(RedisConnection connection) throws DataAccessException {
				return connection.sUnion(keys);
			}
		});
	}

	/**
	 * 获取指定key列表所有set的并集
	 */
	public Set<String> sUnion(String... keys) {
		return StringSerializer.fromBytesSet(this.sUnion(StringSerializer.toBytesArray(keys)));
	}

	/**
	 * 删除指定key的set中的指定value列表
	 */
	private long sRem(final byte[] key, final byte[]... values) {
		return redisTemplate.execute(new RedisCallback<Long>() {

			public Long doInRedis(RedisConnection connection) throws DataAccessException {
				return connection.sRem(key, values);
			}
		});
	}

	/**
	 * 删除指定key的set中的指定value列表
	 */
	public long sRem(String key, String... values) {
		return this.sRem(StringSerializer.toByteArray(key), StringSerializer.toBytesArray(values));
	}

	/**
	 * 获取指定key的set的size
	 */
	private long sCard(final byte[] key) {
		return redisTemplate.execute(new RedisCallback<Long>() {

			public Long doInRedis(RedisConnection connection) throws DataAccessException {
				return connection.sCard(key);
			}
		});
	}

	/**
	 * 获取指定key的set的size
	 */
	public long sCard(String key) {
		return this.sCard(StringSerializer.toByteArray(key));
	}

	/**
	 * 判断指定key的set是否包含指定value
	 */
	private boolean sIsMember(final byte[] key, final byte[] value) {
		return redisTemplate.execute(new RedisCallback<Boolean>() {

			public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
				return connection.sIsMember(key, value);
			}
		});
	}

	/**
	 * 判断指定key的set是否包含指定value
	 */
	public boolean sIsMember(String key, String value) {
		return this.sIsMember(StringSerializer.toByteArray(key), StringSerializer.toByteArray(value));
	}

	/**
	 * ping
	 */
	public String ping() {
		return redisTemplate.execute(new RedisCallback<String>() {

			public String doInRedis(RedisConnection connection) throws DataAccessException {
				return connection.ping();
			}
		});
	}

}
